#include "stm32f10x_flash.h"
#include "flash_ops.h"
#define CONFIG_FLASH_ADDR  0x0800FC00  // ??????????(????????)

// ?? Flash ?(???)
static void Flash_ErasePage(uint32_t pageAddr) {
    FLASH_Unlock();
    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
    FLASH_ErasePage(pageAddr);
    FLASH_Lock();
}

// ????? Flash(???,? 16 ???)
void Save_DeviceConfig_To_Flash(device_config_t *config) {
    uint32_t i;
    uint16_t *pSrc = (uint16_t*)config;
    uint32_t flashAddr = CONFIG_FLASH_ADDR;

    // ?????
    Flash_ErasePage(flashAddr);

    // ?? Flash
    FLASH_Unlock();

    // ????(???? 16 ?)
    for (i = 0; i < sizeof(device_config_t); i += 2) {
        FLASH_ProgramHalfWord(flashAddr + i, *pSrc++);
    }

    // ?? Flash
    FLASH_Lock();
}

// ? Flash ????
void Load_DeviceConfig_From_Flash(device_config_t *config) {
    uint32_t *pFlash = (uint32_t*)CONFIG_FLASH_ADDR;
    uint32_t *pDest = (uint32_t*)config;
    uint32_t i;

    // ? 32 ???,????
    for (i = 0; i < sizeof(device_config_t) / 4; i++) {
        *pDest++ = *pFlash++;
    }

    // ?? Flash ????(? 0xFF)
    if (((uint8_t*)config)[0] == 0xFF) {
        memset(config, 0, sizeof(device_config_t));  // ????
    }
}

void Init_Device_Config(void) {
    // ? Flash ????
    Load_DeviceConfig_From_Flash(&g_device_config);

    // ?? Flash ??(????),????????
    if (g_device_config.product_id[0] == '\0' || g_device_config.product_id[0] == 0xFF) {
        strncpy(g_device_config.product_id, "tr74iK6xFK", MAX_PRODUCT_ID_LEN);
        strncpy(g_device_config.device_name, "MSPDEV003", MAX_DEVICE_NAME_LEN);
        strncpy(g_device_config.token, 
                "version=2018-10-31&res=products%2Ftr74iK6xFK%2Fdevices%2FMSPDEV003&et=9969688899&method=sha1&sign=pyIq%2Btd8INaurl%2F%2FU9RstKM%2BENg%3D",
                MAX_TOKEN_LEN);
        strncpy(g_device_config.battery_json,
                "{\"id\":\"123\",\"params\":{\"BatteryPercentage\":{\"value\":65}}}",
                MAX_BATTERY_JSON_LEN);

        // ??????? Flash
        Save_DeviceConfig_To_Flash(&g_device_config);
    }
}
